#include <ctime>
#include <cstdlib>
#include <iostream>
#include "simulator.h"

using std::cout;
using std::endl;

Deps* selectRandomLeaf(MakefileDeps *forest) {
	forest->lockLeafList();
	vector<Deps *> &deps = forest->GetLeafDeps();
	int remaining = deps.size();
	Deps *ret;

	if (remaining)
		ret = deps[rand() % remaining];
	else
		ret = NULL;
	forest->unlockLeafList();

	return ret;
}

Deps* selectBestLeaf(MakefileDeps *forest) {
//	forest->lockLeafList();
//	vector<Deps *> &deps = forest->GetLeafDeps();
//	Deps *ret = deps.top();
//	forest->unlockLeafList();
  return forest->GetNextLeafToSchedule();
// return forest->RemoveFromMaxLeafHeap();
//	return selectRandomLeaf(forest);	
}


void TCompileJob::run(void *ptr) {
	//MakefileDeps *forest = static_cast<MakefileDeps *>(ptr);
	Deps *dep = static_cast<Deps *>(ptr);
//	unsigned int sleepTime, normalizedFileSize;
	unsigned int sleepTime;
//	unsigned int maxNetworkDelay = 10, minNetworkDelay = 1;
	//	Deps *dep = selectRandomLeaf(forest);

	if (dep == NULL) {
		cout << "NULL dep!" << endl;
		return;
	}
	//	normalizedFileSize = dep->filesize();

	//TODO: Add filesize specific sleep componenet
//	sleepTime = minNetworkDelay + (rand() % (maxNetworkDelay - minNetworkDelay));
	sleepTime = (unsigned int) (dep->exec_time() * 1000000);
//	cout << dep->filename() << " sleeping for: " << sleepTime << endl;
	usleep(sleepTime);

	dep->FinishExecution();
}

void BasicSimulator::start(MakefileDeps *forest) {
	vector<Deps *> &deps = forest->GetLeafDeps();

	while (forest->leafListSize() > 0) {
		TCompileJob *job = new TCompileJob();	//Deleted by TPool itself

		Deps *dep = selectRandomLeaf(forest);

		pool->run(job, (void *) dep, true);
	}

	pool->sync_all();
}

void StaticSimulator::start(MakefileDeps *forest) {
	vector<Deps *> &deps = forest->GetLeafDeps();
	unsigned int numScheduled = 0;
	unsigned int totalNodes = forest->total_deps();

	while (numScheduled != totalNodes) {

		Deps *dep = selectBestLeaf(forest);
		if (dep == NULL) {//Queue is empty, poll again
			cout << "Queue is empty!" << endl;
			usleep(5000);
			continue;
		}
		numScheduled++;

		TCompileJob *job = new TCompileJob();   //Deleted by TPool itself
		pool->run(job, (void *) dep, true);
	}

	pool->sync_all();
}

